using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Web.UI;
using System.Web.UI.HtmlControls;

namespace TST.WebParts
{
    internal sealed class SelectWebPropertyEditor : EditorPart
    {
        private const string PROPERTYBAGPREFIX = "_PRBAG_"; 
        private const string EMPTYITEM = "EMPTY";
        private DropDownList _selectCurrentSite;
        private DropDownList _selectParentSite;
        private DropDownList _selectRootSite;
        private RadioButtonList _selectMultivalueHandling;
        private TextBox _getValueSeparator;

        public SelectWebPropertyEditor(string webPartID)
        {
            this.ID = string.Format("SelectWebPropertyEditor{0}", webPartID);
            this.Title = "Web Context Filter options";
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            CreateOptions();
        }

        private void CreateOptions()
        {
            HtmlTable table = new HtmlTable();
            table.CellPadding = 5;
            table.CellSpacing = 3;
            Controls.Add(table);

            HtmlTableRow rowCurrent = new HtmlTableRow();
            table.Controls.Add(rowCurrent);
            HtmlTableCell cellCurrent = new HtmlTableCell();
            rowCurrent.Controls.Add(cellCurrent);

            Label description = new Label();
            description.Text = "<strong>Current site</strong>: select a property";
            cellCurrent.Controls.Add(description);

            cellCurrent.Controls.Add(new LiteralControl("<br>"));

            _selectCurrentSite = new DropDownList();
            cellCurrent.Controls.Add(_selectCurrentSite);
            _selectCurrentSite.Items.Add(new ListItem("-- Select a property --", string.Empty));
            AddItems(_selectCurrentSite, SPContext.Current.Web);
            foreach (string s in SPContext.Current.Web.Properties.Keys)
            {
                ListItem item = GetListItemForPropertyBagItem(s, SPContext.Current.Web);
                if (item != null)
                {
                    _selectCurrentSite.Items.Add(item);
                }
            }

            HtmlTableRow rowParent = new HtmlTableRow();
            table.Controls.Add(rowParent);
            HtmlTableCell cellParent = new HtmlTableCell();
            rowParent.Controls.Add(cellParent);

            Label parentDescription = new Label();
            parentDescription.Text = "<strong>Parent site:</strong> select a property";
            cellParent.Controls.Add(parentDescription);

            cellParent.Controls.Add(new LiteralControl("<br>"));

            _selectParentSite = new DropDownList();
            cellParent.Controls.Add(_selectParentSite);
            _selectParentSite.Items.Add(new ListItem("-- Select a property --", string.Empty));
            using (SPWeb parent = SPContext.Current.Web.ParentWeb)
            {
                if (parent != null)
                {
                    AddItems(_selectParentSite, parent);
                    foreach (string s in parent.Properties.Keys)
                    {
                        ListItem item = GetListItemForPropertyBagItem(s, parent);
                        if (item != null)
                        {
                            _selectParentSite.Items.Add(item);
                        }
                    }
                }
            }

            HtmlTableRow rowRoot = new HtmlTableRow();
            table.Controls.Add(rowRoot);
            HtmlTableCell cellRoot = new HtmlTableCell();
            rowRoot.Controls.Add(cellRoot);

            Label rootDescription = new Label();
            rootDescription.Text = "<strong>Root site:</strong> select a property";
            cellRoot.Controls.Add(rootDescription);

            cellRoot.Controls.Add(new LiteralControl("<br>"));

            _selectRootSite = new DropDownList();
            cellRoot.Controls.Add(_selectRootSite);
            _selectRootSite.Items.Add(new ListItem("-- Select a property --", string.Empty));
            SPWeb root = SPContext.Current.Site.RootWeb;
            try
            {
                AddItems(_selectRootSite, root);
                foreach (string s in root.Properties.Keys)
                {
                    ListItem item = GetListItemForPropertyBagItem(s, root);
                    if (item != null)
                    {
                        _selectRootSite.Items.Add(item);
                    }
                }
            }
            finally
            {
                if (root.ID != SPContext.Current.Web.ID)
                {
                    root.Dispose();
                }
            }

            HtmlTableRow rowMultivalueHandling = new HtmlTableRow();
            table.Controls.Add(rowMultivalueHandling);
            HtmlTableCell cellMultivalueHandling = new HtmlTableCell();
            rowMultivalueHandling.Controls.Add(cellMultivalueHandling);
            Label valueMultivalueHandling = new Label();
            valueMultivalueHandling.Text = "Select how multiple values are handled";
            cellMultivalueHandling.Controls.Add(valueMultivalueHandling);

            cellMultivalueHandling.Controls.Add(new LiteralControl("<br>"));
            _selectMultivalueHandling = new RadioButtonList();
            _selectMultivalueHandling.Items.Add( new ListItem(FilterMultipleValueHandling.SendAll.ToString(), FilterMultipleValueHandling.SendAll.ToString()));
            _selectMultivalueHandling.Items.Add( new ListItem(FilterMultipleValueHandling.SendFirst.ToString(), FilterMultipleValueHandling.SendFirst.ToString()));
            _selectMultivalueHandling.Items.Add( new ListItem(FilterMultipleValueHandling.Combine.ToString(), FilterMultipleValueHandling.Combine.ToString()));
            cellMultivalueHandling.Controls.Add(_selectMultivalueHandling);

            HtmlTableRow rowValueSeparator = new HtmlTableRow();
            table.Controls.Add(rowValueSeparator);
            HtmlTableCell cellValueSeparator = new HtmlTableCell();
            rowValueSeparator.Controls.Add(cellValueSeparator);
            Label valueSeparatorDescription = new Label();
            valueSeparatorDescription.Text = "Value separator (used to combine multiple values)";
            cellValueSeparator.Controls.Add(valueSeparatorDescription);

            cellValueSeparator.Controls.Add(new LiteralControl("<br>"));
            _getValueSeparator = new TextBox();
            cellValueSeparator.Controls.Add(_getValueSeparator);

            HtmlTableRow rowHelp = new HtmlTableRow();
            table.Controls.Add(rowHelp);
            HtmlTableCell cellHelp = new HtmlTableCell();
            rowHelp.Controls.Add(cellHelp);

            Label helpDescription = new Label();
            helpDescription.Text = "You can select a property for each of the 3 sites. This can be one of the <i>fixed properties</i> that this web part supports, or one of the properties from the <i>property bag</i>. The dropdowns show the name of the property and the current value, to give you an idea of what will be sent as the filter value.<br>If you select <i>multiple properties</i>, the web part sends all values, or just the first that has a value. This depends on the 'Advanced Filter Options' above.";
            cellHelp.Controls.Add(helpDescription);

        }

        private void AddItems(DropDownList selectList, SPWeb web)
        {
            if (selectList == null || web == null)
                return;
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.Title, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.Name, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.Language, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.LocaleLCID, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.LocaleName, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.CurrentUser, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.UserIsSiteAdmin, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.UserIsWebAdmin, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.Author, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.SiteCollectionOwner, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.WebTemplate, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.PortalName, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.PortalUrl, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.AssociatedVisitorGroup, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.AssociatedMemberGroup, web));
            selectList.Items.Add(GetListItemForProperty(FixedWebProperties.AssociatedOwnerGroup, web));
        }

        private ListItem GetListItemForProperty(FixedWebProperties property, SPWeb web)
        {
            string title = GetTitleForProperty(property);
            string value = GetValueForProperty(property, web);
            if (string.IsNullOrEmpty(value))
            {
                value = "<< empty >>";
            }
            return new ListItem(string.Format("{0} ({1})", title, value), property.ToString());
        }

        private ListItem GetListItemForPropertyBagItem(string name, SPWeb web)
        {
            if (name.StartsWith("vti_", StringComparison.OrdinalIgnoreCase) || name.StartsWith("_"))
                return null;
            string title = string.Format("Property bag: {0}", name);
            if (web == null || !web.Properties.ContainsKey(name))
            {
                return null;
            }
            string value = web.Properties[name];
            if (string.IsNullOrEmpty(value))
            {
                value = "<< empty >>";
            }
            return new ListItem(string.Format("{0} ({1})", title, value), string.Format("{0}{1}", PROPERTYBAGPREFIX, name));
        }

        public static string GetValueForProperty(FixedWebProperties property, SPWeb web)
        {
            if (web == null)
            {
                return null;
            }
            string value = null;
            switch (property)
            {
                case FixedWebProperties.AssociatedMemberGroup:
                    if (web.AssociatedMemberGroup != null)
                        value = web.AssociatedMemberGroup.Name;
                    break;
                case FixedWebProperties.AssociatedOwnerGroup:
                    if (web.AssociatedOwnerGroup != null)
                        value = web.AssociatedOwnerGroup.Name;
                    break;
                case FixedWebProperties.AssociatedVisitorGroup:
                    if (web.AssociatedVisitorGroup != null)
                        value = web.AssociatedVisitorGroup.Name;
                    break;
                case FixedWebProperties.Author:
                    if (web.Author != null)
                        value = web.Author.Name;
                    break;
                case FixedWebProperties.CurrentUser:
                    value = web.CurrentUser.Name;
                    break;
                case FixedWebProperties.Language:
                    value = web.Language.ToString();
                    break;
                case FixedWebProperties.LocaleLCID:
                    value = web.Locale.LCID.ToString();
                    break;
                case FixedWebProperties.LocaleName:
                    value = web.Locale.Name;
                    break;
                case FixedWebProperties.MasterUrl:
                    value = web.MasterUrl;
                    break;
                case FixedWebProperties.Name:
                    value = web.Name;
                    break;
                case FixedWebProperties.PortalName:
                    value = web.PortalName;
                    break;
                case FixedWebProperties.PortalUrl:
                    value = web.PortalUrl;
                    break;
                case FixedWebProperties.RequestAccessEmail:
                    value = web.RequestAccessEmail;
                    break;
                case FixedWebProperties.Title:
                    value = web.Title;
                    break;
                case FixedWebProperties.Url:
                    value = web.Url;
                    break;
                case FixedWebProperties.UserIsSiteAdmin:
                    value = web.UserIsSiteAdmin.ToString();
                    break;
                case FixedWebProperties.UserIsWebAdmin:
                    value = web.UserIsWebAdmin.ToString();
                    break;
                case FixedWebProperties.WebTemplate:
                    value = web.WebTemplate;
                    break;
                case FixedWebProperties.SiteCollectionOwner:
                    SPSite site = web.Site;
                    if (site.Owner != null)
                        value = site.Owner.Name;
                    break;
            }
            return value;
        }

        public static string GetTitleForProperty(FixedWebProperties property)
        {
            string title = string.Empty;
            switch (property)
            {
                case FixedWebProperties.AssociatedMemberGroup:
                    title = "Member group";
                    break;
                case FixedWebProperties.AssociatedOwnerGroup:
                    title = "Owner group";
                    break;
                case FixedWebProperties.AssociatedVisitorGroup:
                    title = "Visitor group";
                    break;
                case FixedWebProperties.Author:
                    title = "Author";
                    break;
                case FixedWebProperties.CurrentUser:
                    title = "Current user";
                    break;
                case FixedWebProperties.Language:
                    title = "Language";
                    break;
                case FixedWebProperties.LocaleLCID:
                    title = "Locale LCID";
                    break;
                case FixedWebProperties.LocaleName:
                    title = "Locale name";
                    break;
                case FixedWebProperties.MasterUrl:
                    title = "Master url";
                    break;
                case FixedWebProperties.Name:
                    title = "Name";
                    break;
                case FixedWebProperties.PortalName:
                    title = "Portal name";
                    break;
                case FixedWebProperties.PortalUrl:
                    title = "Portal url";
                    break;
                case FixedWebProperties.RequestAccessEmail:
                    title = "Request access email address";
                    break;
                case FixedWebProperties.Title:
                    title = "Title";
                    break;
                case FixedWebProperties.Url:
                    title = "Url";
                    break;
                case FixedWebProperties.UserIsSiteAdmin:
                    title = "User is site admin";
                    break;
                case FixedWebProperties.UserIsWebAdmin:
                    title = "User is web admin";
                    break;
                case FixedWebProperties.WebTemplate:
                    title = "Web template";
                    break;
                case FixedWebProperties.SiteCollectionOwner:
                    title = "Site collection owner";
                    break;
            }
            return title;
        }

        public override bool ApplyChanges()
        {
            WebPropertyFilter webpart = WebPartToEdit as WebPropertyFilter;
            webpart.CurrentSiteProperty = _selectCurrentSite.SelectedValue;
            webpart.ParentSiteProperty = _selectParentSite.SelectedValue;
            webpart.RootSiteProperty = _selectRootSite.SelectedValue;
            webpart.MultipleValueHandling = (FilterMultipleValueHandling)Enum.Parse(typeof(FilterMultipleValueHandling), _selectMultivalueHandling.SelectedValue);
            webpart.ValueSeparator = _getValueSeparator.Text;
            return true;
        }

        public override void SyncChanges()
        {
            EnsureChildControls();
            WebPropertyFilter webpart = WebPartToEdit as WebPropertyFilter;
            if (webpart.CurrentSiteProperty != null)
                _selectCurrentSite.SelectedValue = webpart.CurrentSiteProperty;
            if (webpart.ParentSiteProperty != null)
                _selectParentSite.SelectedValue = webpart.ParentSiteProperty;
            if (webpart.RootSiteProperty != null)
                _selectRootSite.SelectedValue = webpart.RootSiteProperty;
            _selectMultivalueHandling.SelectedValue = webpart.MultipleValueHandling.ToString();
            if (String.IsNullOrEmpty(webpart.ValueSeparator))
            {
                _getValueSeparator.Text = ";";
            }
            else
            {
                _getValueSeparator.Text = webpart.ValueSeparator;
            }
        }

        internal static string GetValueForProperty(string propertyName, SPWeb web)
        {
            if (web == null || string.IsNullOrEmpty(propertyName))
                return null;

            if (propertyName.StartsWith(PROPERTYBAGPREFIX))
            {
                string webProperty = propertyName.Replace(PROPERTYBAGPREFIX, string.Empty);
                if (web.Properties.ContainsKey(webProperty))
                {
                    return web.Properties[webProperty];
                }
            }
            else
            {
                try
                {
                    FixedWebProperties property = (FixedWebProperties)Enum.Parse(typeof(FixedWebProperties), propertyName, true);
                    return GetValueForProperty(property, web);
                }
                catch (Exception)
                {
                    throw new Exception(string.Format("'{0}' is not a valid web property.", propertyName));
                }
            }
            return null;
        }
    }

    public enum FixedWebProperties
    {
        AssociatedMemberGroup,
        AssociatedOwnerGroup,
        AssociatedVisitorGroup,
        Author,
        CurrentUser,
        Language,
        LocaleLCID,
        LocaleName,
        MasterUrl,
        Name,
        PortalName,
        PortalUrl,
        RequestAccessEmail,
        Title,
        Url,
        UserIsSiteAdmin,
        UserIsWebAdmin,
        WebTemplate,
        SiteCollectionOwner
    }
}
